/*** Class Name: WorkflowEditController 
 * Author: Accenture
 * Date: 21-Oct-2011
 * Requirement/Project Name: iFulfill
 * Requirement Description: Controller for Workflow Edit page.
 **/
 

public with sharing class WorkflowEditController 
{ 
 
  public list<String> selectedStageNames{get;set;} 
  public list<wrapperOut> wrapout{get;set;}
  Public list<stageWrapper> Stages{get;set;}
  public List<AGWrapper> asgnGroups{get;set;}   
  private Workflow_definition__c WF;  
  private List<Workflow_Stage__c> selStages;

  /*
   *  Constructor 
   *
   **/
  public WorkflowEditController(ApexPages.StandardController controller) 
  {
        WF = (Workflow_definition__c)controller.getRecord();
        //Calls to populate the pre selected stages and tasks
        selectedStages();
        initilizeAssignmentGroup();
        initilizeTaskAndActivities ();

    }
 
 // Wrapper class for workflow stage
    
 Class stageWrapper
 {
        public Workflow_Stage__c SD{get;set;}
        public boolean selectbox{get;set;}        
        public stageWrapper(Workflow_Stage__c S, boolean chkbox){
            SD =S;
            selectbox =chkbox;
        }
 }   
  // Wrapper class for Assignment group 
  
     Class AGWrapper
     {
        public Assignment_Group_Name__c AGroup{get;set;}
        public boolean selectbox{get;set;}
        public string functionName{get;set;}        
        public AGWrapper(Assignment_Group_Name__c AG, boolean chkbox, string func){
            system.debug('GGGGG'+AG);
            system.debug('checkbox'+chkbox);
            system.debug('function'+func);
            
            AGroup=AG;
            selectbox =chkbox;
            functionName = func;
        }
    }
     // Wrapper class for workflow Step
     
     Class StepWrapper
     {
        public Wokflow_Steps__c  StepDef{get;set;}
        public boolean selbox{get;set;}    
        public String defaultAG{get;set;}    
        public List<SelectOption> funcGroups{get;set;}  
        public stepWrapper(){}      
        public stepWrapper(Wokflow_Steps__c  S, boolean chkbox, String defaultGrp,List<SelectOption> funcGrps ){
            StepDef =S;
            selbox =chkbox;
            defaultAG = defaultGrp;
            funcGroups = funcGrps ;
        }
    }
 
    // Wrapper class for Activity Def
     Class ActWrapper{
        public Activities_definition__c AD{get;set;}
        public boolean slctbox{get;set;}        
        public ActWrapper(Activities_definition__c A, boolean chkbox){
            AD =A;
            slctbox =chkbox;
        }
        public ActWrapper(){}
    }
    
    
    Class WrapperOut
    {
        public List<ActWrapper> Act{get;set;}
        public stepWrapper step{get;set;}        
        public wrapperOut(){
            if(step==null){step= new stepWrapper();}
            if(Act==null){Act= new List<ActWrapper>();}           
        }
    }         
   
   /*
    * Fetchs the selected workflow stages.
    *
    *
    **/
    
   public void selectedStages()
   {
       Stages =  new list<stageWrapper>();
       selectedStageNames = new list<string>();       
       selStages = [select name ,Stage__c,Stage__r.name,sequence__C from Workflow_Stage__c where workflow_code__c = :WF.Id order by sequence__C];
      
       for(Workflow_Stage__c ST :selStages)
       {
            selectedStageNames.add(ST.Stage__r.name);
            Stages.add(new stageWrapper(ST, true));
        }  
   }
   
   /*
    *
    * Fetchs the selected Assignment Group.
    *
    **/ 
   public void initilizeAssignmentGroup()
   {
   
       // Maps the stage id with workflowStage 
       Map<ID, Workflow_Stage__c> workflowStageMap  = new Map<ID, Workflow_Stage__c>();
       
       Set<id> stageIds = new Set<id>();
       asgnGroups = new list<AGWrapper>(); 
       Set<String> wfAssignmentGroup = new Set<String>();
       for(Workflow_Stage__c obj : selStages )
       {
            workflowStageMap.put(obj.Stage__c, obj);
            stageIds.add(obj.id);
       }
       List<WF_Assignment_Group__c> wfAssinmentGroup = [Select  AG_Definition__c , Workflow_Function__c from WF_Assignment_Group__c where Workflow_Function__C  in :stageIds ];
       for(WF_Assignment_Group__c wfAssignGroupObj : wfAssinmentGroup) 
       {
               String s = wfAssignGroupObj.Workflow_Function__c+'::'+ wfAssignGroupObj.AG_Definition__c;
               wfAssignmentGroup.add(s );
       }
       for(Workflow_Stage__c obj : selStages )
       {
           String funcName = obj.Name;
           // Cannot be  Bulkify 
           List<Assignment_Group_Name__c> Groups  = [select name, id from Assignment_Group_Name__c where function__c  INCLUDES (:obj.Name) and type__c = 'Fulfillment'] ;                                 
           for(Assignment_Group_Name__c Grp:Groups)
           {
                // Check if user has selected the assignment group
                if(workflowStageMap.get(obj.stage__c) != null &&  wfAssignmentGroup.contains(  workflowStageMap.get(obj.stage__c).id +'::'+Grp.id) )
                {    
                     asgnGroups.add(new AGWrapper(Grp,true,funcName)); 
                }                        
           }                        
        }    
   }

   /*
    *
    * Fetchs the selected Task and activities.
    *
    **/    
   public void initilizeTaskAndActivities ()
   {    
        // Maps and stores the step id with associated activities 
        Map<ID,List<Activities_definition__c>>  StepActMAP = new Map<ID,List<Activities_definition__c>>(); 
        // Map the the step id with workflowSteps id 
        Map<id,id> groupIds = new Map<id,id>();
        // Stores the activity is requried are not
        Map<id,boolean> stepActivityMap = new Map<id,boolean>(); 
        Set<id> stageIds = new Set<id>();  
        wrapout = new list<wrapperOut>();
        
        for(Workflow_Stage__c obj : selStages )
        { 
            stageIds.add(obj.Stage__C);
       }
        List<Wokflow_Steps__c> seltaskList = [select id,Step__c,name,Wokflow_Stage_Name__r.Stage__r.name  ,Sequence__c,Target_Days__c,Dashboard_Function__c,Default_Group__c from Wokflow_Steps__c where Wokflow_Stage_Name__c in :selStages];        
        List<Step_Definition__c> StepList = [select id,name,step_definition__c.Stage__r.name,Step_Sequence__c,Target_Days__c,Dashboard_Function__c from step_definition__c where status__c='Active' and stage__c in :stageIds order by stage__c];        
        list<Workflow_Activities__c> selActList = [select id,name,Activity__c,Activity_Description__c, status__c,required__C,Step_Name__r.name,Step_Name__c,Step_Name__r.Wokflow_Stage_Name__r.name,Step_Name__r.Target_Days__c,Step_Name__r.Dashboard_Function__c from Workflow_Activities__c where Step_Name__c in :seltaskList ];           
       
        for(Activities_definition__c ActList : [select id,name,Activity_Description__c, status__c,required__C,step__r.name,step__c,step__r.Stage__r.name,step__r.Target_Days__c,step__r.Dashboard_Function__c from Activities_definition__c where status__c = 'Active' and step__c in :StepList])
        {
                if(StepActMAP.containsKey(ActList.step__c))
                {
                    StepActMAP.get(ActList.step__c).add(ActList);//adds activities for this step to the activity list in the map    
                }
                else
                {
                    StepActMAP.put(ActList.step__c,new List<Activities_definition__c>{ActList});//adds new activity list for this step to the map    
                }
        }
        
        
        
           for(Workflow_Activities__c AL :selActList )
           {
               stepActivityMap.put(AL.Activity__c,AL.required__C);
           }    
           
       
       for(Wokflow_Steps__c obj1 : seltaskList)
       {
                wrapperOut tmpwrapper = new wrapperOut();                
                list<SelectOption> tskGrpOptions = new list<SelectOption>();
                for(AGWrapper Gp :asgnGroups)
                {  
                     // check Function name with asscosiated assignment group
                     if(obj1.Wokflow_Stage_Name__r.Stage__r.name == Gp.functionName && Gp.selectbox){
                           tskGrpOptions.add(new SelectOption(Gp.AGroup.id,Gp.AGroup.Name)); 
                   } 
                     
                }               
                tmpwrapper.Step=new stepWrapper(obj1, true,groupIds.get(obj1.id),tskGrpOptions);     
                List<ActWrapper> twrap2=new List<ActWrapper>(); 

                if(StepActMAP.containsKey(obj1.Step__c))
                {
                    for(Activities_definition__c ActDef : StepActMAP.get(obj1.Step__c))
                    {
                        // check if user as selected the activity
                        if(stepActivityMap.containsKey(ActDef.id))
                        {
                            ActDef.required__C = stepActivityMap.get(ActDef.id);
                            twrap2.add(new ActWrapper(ActDef, True));
                         }   
                        else
                        {
                            twrap2.add(new ActWrapper(ActDef, False));
                        }
                    }
                }
                tmpwrapper.Act = twrap2 ;                
                wrapout.add(tmpwrapper);
            }            
   }
   
   /*
    * 
    *  Save the the selected workflow task and activities
    * 
    **/    
   public Pagereference  saveUpdatedWFDefn()
   {
       Pagereference Page = null;
        try
        {
            update WF;
            insertWorkflowActivitiesAndTask();
             Page = new Pagereference('/apex/WorkflowdefinitionSummaryView?id='+WF.id);     
        }
        catch(DMLException e)
        {
           GeneralConstants.mailAnyExceptionToMe('WorkFLowController','SaveSteps: Insert Steps failed',e);
        }
           
        return Page;
   } 
    /*
    * 
    *  Insert the Workflow Activities
    * 
    **/          
    private void insertWorkflowActivitiesAndTask()
    {
        // Map the the step id with workflowSteps id 
        Map<id,id> stepMap = new Map<id,id>(); 
        // Maps and stores the step id with associated activities
        Map<id,Workflow_Activities__c> stepActivityMap = new Map<id,Workflow_Activities__c>(); 
        
        List<Workflow_Activities__c> updateWfAct  = new List<Workflow_Activities__c>();
        List<Wokflow_Steps__c> updateWfSteps =  new List<Wokflow_Steps__c>();
      
        list<Wokflow_Steps__c> StepIds = [select id, step__c from Wokflow_Steps__c where Wokflow_Stage_Name__r.Workflow_Code__c = :WF.id];
        List<Wokflow_Steps__c> seltaskList = [select id,Step__c,name,Wokflow_Stage_Name__r.Stage__r.name  ,Sequence__c,Target_Days__c,Dashboard_Function__c,Default_Group__c from Wokflow_Steps__c where Wokflow_Stage_Name__c in :selStages];        
        list<Workflow_Activities__c> selActList = [select id,name,Activity__c,Activity_Description__c, status__c,required__C,Step_Name__r.name,Step_Name__c,Step_Name__r.Wokflow_Stage_Name__r.name,Step_Name__r.Target_Days__c,Step_Name__r.Dashboard_Function__c from Workflow_Activities__c where Step_Name__c in :seltaskList ];           
        

        for(Workflow_Activities__c AL :selActList )
        {
            stepActivityMap.put(AL.Activity__c,AL ) ;
        }  
        for(Wokflow_Steps__c  s: StepIds )
        {
          stepMap.put(s.step__c,s.id);
        } 
        
        for(integer i=0 ; i< wrapOut.size(); i++)
        {
            updateWfSteps.add(wrapOut[i].step.StepDef);
            for(integer j=0 ; j< wrapOut[i].Act.size(); j++)
            {
              // Check if the user has selected the acvitity
              if(wrapOut[i].Act[j].slctbox)
              {
                  // Check user is modified the existing activity
                  if(stepActivityMap.containsKey(wrapOut[i].Act[j].AD.id))
                  {
                      Workflow_Activities__c tempWfAct = stepActivityMap.get(wrapOut[i].Act[j].AD.id);
                      tempWfAct.required__C = boolean.valueof(wrapOut[i].Act[j].AD.Required__C);                      
                       updateWfAct.add(tempWfAct);
                  }
                  else
                  {
                    // user is trying to add new activity
                    Workflow_Activities__c WFAct = new Workflow_Activities__c();
                    WFAct.Step_Name__c = stepMap.get(wrapOut[i].Act[j].AD.step__c);
                    WFAct.Name = wrapOut[i].Act[j].AD.name;
                    WFAct.Activity__c = wrapOut[i].Act[j].AD.id;
                    WFAct.required__C = boolean.valueof(wrapOut[i].Act[j].AD.Required__C);
                    updateWfAct.add(WFAct);
                  }
             }
         }
       }      
       // update workflow Steps    
       update updateWfSteps;
       //update and insert the activity
       upsert updateWfAct;
      
    }      
}